/**
 * This file was created by Julia Deeb and Nick Popescu for use in SpaceTrader
 */
import java.awt.Point;
import java.io.Serializable;
import java.util.Random;

/**
 * This class represents a Planet, with associated fields and methods.
 * 
 * @author Nick Popescu, Julia Deeb
 * @version 1.0
 */

public class Planet implements Serializable {

    /**
     * This represents the name of the planet
     */
    private final String name;

    /**
     * This represents the player that is playing the game
     */
    private final Player player;

    /**
     * This represents the location of the planet in respect to the Space
     */
    private final Point location;

    /**
     * This is the location that is used for drawing. It is different because it
     * accounts for window size To determine the planet's relative location.
     */
    private Point visualLocation;

    /**
     * This represents the government of the planet
     */
    private final Government government;

    /**
     * This represents the development level of the planet
     */
    private  final Development development;

    /**
     * This represents the condition of the planet
     */
    private final String condition;

    /**
     * This array represents all the possible items for sale by the planet
     */
    private final Resource[] itemsForSale;

    /**
     * This represents how big the planet is drawn
     */
    private int drawSize = 2; // $codepro.audit.disable numericLiterals

    /**
     * This represents if the mouse is pointing to the planet right now
     */
    private boolean clickable = false;

    /**
     * This represents the marketplace of the planet
     */
    private final Marketplace marketplace;

    /**
     * This represents the space port associated to each planet
     */
    private final SpacePort spacePort;

    /**
     * Creates the planet and sets up its fields.
     * 
     * @param name
     *            The name of the planet.
     * @param location
     *            The location of the planet.
     * @param player
     *            The user of the game
     */

    public Planet(String name, Point location, Player player) {
	this.name = name;
	this.player = player;
	this.location = location;
	this.development = new Development(); // Automatically makes a random
					      // development.
	this.government = new Government(development.getTechLevel()); // Picks a
								      // random
								      // government.
	this.condition = development.getCondition();
	this.itemsForSale = makeResources();
	this.spacePort = new SpacePort();
	calcPrices(itemsForSale);
	calcMultiplicity(itemsForSale);

	this.marketplace = new Marketplace(this, player);

	System.out.println("Created " + name + " at x: " + location.x + ", y: "
		+ location.y);
    }

    /**
     * Calculates how many of each item is available for sale on this planet.
     * 
     * @param arr
     *            Array of resources on this planet.
     */
    private void calcMultiplicity(Resource[] arr) {
	final Random rand = new Random();
	for (Resource res : arr) {
	    if (res.favoredTechLevel() == development.getTechLevel()) {
		res.setMultiplicity(100); // $codepro.audit.disable
					  // numericLiterals
	    } else {
		res.setMultiplicity(rand.nextInt(80)); // $codepro.audit.disable
						       // numericLiterals
	    }
	}
    }

    /**
     * Calculates the prices for all the items that are sold on this planet.
     * 
     * @param arr
     *            The array of resources for sale on this planet.
     */
    private void calcPrices(Resource[] arr) {
	final Random rand = new Random();
	for (Resource res : arr) {
	    int var = rand.nextInt(res.getMaxVariance());
	    if (res.incPrice().equals(development.getCondition())) {
		var = res.getMaxVariance();
	    } else if (res.decPrice().equals(development.getCondition())) {
		var = 0;
	    }
	    int price = res.getBasePrice()
		    + (res.getIPL() * (development.getTechLevel()) - res
			    .getMinTechLevel()) + var;
	    res.setPrice(price);
	}
    }

    /**
     * Makes all the available resources that are on this planet.
     * 
     * @return Array of resources on this planet.
     */
    private Resource[] makeResources() {
	final Resource temp = new Resource(0);
	final Resource[] arr = new Resource[temp.getTypes(development
		.getTechLevel()).length];
	for (int i = 0; i < temp.getTypes(development.getTechLevel()).length; i++) {
	    arr[i] = new Resource(i);
	}
	return arr;
    }

    /**
     * Used to get an array of resources that are available for sale on this
     * planet.
     * 
     * @return And array of the items that are being sold on this planet.
     */
    public Resource[] getItemsForSale() {
	return this.itemsForSale;
    }

    /**
     * Used to get the location of the planet.
     * 
     * @return A Point representation of the planet's location.
     */
    public Point getLocation() {
	return location;
    }

    /**
     * Used to get the Visual Location of the planet (where it should be drawn).
     * 
     * @return Visual location of the planet (Where it should be drawn).
     */
    public Point getVisualLocation() {
	return visualLocation;
    }

    /**
     * Sets the the Visual Location of the planet (where it should be drawn).
     * 
     * @param visualLocation
     *            The Visual Location of the planet (where it should be drawn).
     */
    public void setVisualLocation(Point visualLocation) {
	this.visualLocation = visualLocation;
    }

    /**
     * Used to get the size that the planet will be when it's drawn.
     * 
     * @return An integer that represents the size of the planet when it is
     *         drawn.
     */
    public int getDrawSize() {
	return drawSize;
    }

    /**
     * Used to set the Draw Size of the planet (the size that it will be when
     * drawn.
     * 
     * @param drawSize
     *            What size the planet should be when it's drawn.
     */
    public void setDrawSize(int drawSize) {
	this.drawSize = drawSize;
    }

    /**
     * Sets if the planet is currently Clickable (if the mouse is hovering over
     * it).
     * 
     * @param flag
     *            True if the mouse is hovering over the planet, false
     *            otherwise.
     */
    public void setClickable(boolean flag) {
	this.clickable = flag;
    }

    /**
     * Checks if the planet is currently Clickable (if the mouse is hovering
     * over it).
     * 
     * @return True if clickable, false otherwise.
     */
    public boolean isClickable() {
	return clickable;
    }

    /**
     * Used to get the name of the planet.
     * 
     * @return Name of the planet.
     */
    public String getName() {
	return name;
    }

    /**
     * Used to get the type of government of the planet.
     * 
     * @return The government of the planet.
     */
    public String getGovernment() {
	return government.getGovtType();
    }

    /**
     * Used to get the type of development of the planet.
     * 
     * @return The development of the planet.
     */
    public String getDevelopment() {
	return development.getType();
    }

    /**
     * Used to get a reference to the Marketplace on this planet.
     * 
     * @return The Marketplace reference on this planet.
     */
    public Marketplace getMarketplace() {
	return marketplace;
    }

    /**
     * Used to get a reference to the SpacePort on this planet.
     * 
     * @return The SpacePort reference on this planet.
     */
    public SpacePort getSpacePort() {
	return spacePort;
    }

    /**
     * This method returns a string representing the Planet class
     * 
     * @return a string representing the planet class
     */
    public String toString() {
	return this.toString();
    }
}
